package com.tqfframe.studydemo.mySocketRpc.core;


import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

/**
 * @Author: 唐祺峰
 * @Date: 2020/12/4 0004 9:34
 * @Version 1.0
 */


public class RpcServer implements Server {

    final static String  RPC_SERVER_PORT="RPC_SERVER_PORT";
    //rpc服务接口
    final static String  RPC_SERVER_INTERFACE="RPC_SERVER_INTERFACE";

//    //装用实现类的bena
//    static Map<String,Class> RESmap;
//    //加载所有需要注册的额服务
//    static {
//        //这里可以用Aop 加注解的方式来把需要暴露的服务，注册到服务列表里面去
//        RESmap=new ConcurrentHashMap<>();
//
//        //把服务注册到注册表
//        RESmap.put(GODService.class.getName(),GODServiceImpl.class);
//
//    }

    @Override
    public void Handler() throws IOException {
        //读取配置文件
        Properties properties = new Properties();
        InputStream resourceAsStream = RpcServer.class.getClassLoader().getResourceAsStream("rpc/RpcServerConfig.properties");
        properties.load(resourceAsStream);
        Integer port =new Integer((String) properties.get(RPC_SERVER_PORT));
        String rpc_interface =(String) properties.get(RPC_SERVER_INTERFACE);
        //启动rSocket服务器
        ServerSocket serverSocket = new ServerSocket(port);

        //采取传统的bio处理
        while (true){
            //等待客服端链接，serverSocket.accept()方法里面有一个accept0方法，这个是native方法，具体来说就是与操作系统交互来实现监听指定端口上是否有客户端接入，
            // 正是因为accept0在没有客户端接入的时候会一直处于阻塞状态，所以造成了我们程序级别的accept方法阻塞
            Socket accept = serverSocket.accept();
            System.out.println("有客户端连接拉");
            new Thread(()->{
                try {
                    //等待客户端输入
                    ObjectInputStream in= new ObjectInputStream(accept.getInputStream());
                    //获取客户端传过来的类名称
                    String className = (String) in.readObject();

                    //获取客户端客服端传过来的方法名称
                    String methodName=(String) in.readObject();

                    //获取客户端传过来的参数
                    Object[] args = (Object[]) in.readObject();

                    //获取客服的端传过来的参数类型
                    Class[] argsType = (Class[]) in.readObject();

                    //从注册表中获取服务的字节码
//                    Class aClass = RESmap.get(className);
                    Class aClass =Class.forName(rpc_interface);
                    //通过字节码对象获取构造器
//                    Constructor constructor = aClass.getConstructor();
//                    constructor.setAccessible(true);
                    Constructor constructor=aClass.getConstructor();
                    //通过反射的方式创建对象并且执行对象的方法
                    Object invoke = aClass.getMethod(methodName,argsType).invoke(constructor.newInstance(), args);

                    //把返回结果写回给客户端
                    ObjectOutputStream returnObject=new ObjectOutputStream(accept.getOutputStream());
                    returnObject.writeObject(invoke);
                    //关闭流
                    in.close();
                    returnObject.close();
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }).start();


        }


    }


}